#pragma once
#include <string>
#include <memory>
#include <iostream>
#include <vector>
#include "LogEvent.h"
#include "LogLevel.h"

namespace log
{

class LogLayout
{
public:
    using ptr = std::shared_ptr<LogLayout>;

    class LogLayoutItem
    {
    public:
        using ptr = std::shared_ptr<LogLayoutItem>;
        LogLayoutItem() {}
        virtual void format(std::ostream& os, const LogEvent::ptr ptrEvent) = 0;
    };

    std::string format(const LogEvent::ptr ptrEvent);
    void addLogLayoutItem(LogLayoutItem::ptr ptrItem) { m_vecItems.push_back(ptrItem); }

private:
    std::vector<LogLayoutItem::ptr> m_vecItems;
};

class YearLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<YearLayoutItem>; 
    YearLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class MouthLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<MouthLayoutItem>; 
    MouthLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
  
class DayLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<DayLayoutItem>; 
    DayLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class HourLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<HourLayoutItem>; 
    HourLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class MinLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<MinLayoutItem>; 
    MinLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class SecondLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<SecondLayoutItem>; 
    SecondLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class MSecLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<MSecLayoutItem>; 
    MSecLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class LevelLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<LevelLayoutItem>; 
    LevelLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class ThreadIdLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<ThreadIdLayoutItem>; 
    ThreadIdLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
    
class FileLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<FileLayoutItem>; 
    FileLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class LineLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<LineLayoutItem>; 
    LineLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
 
class FuncLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<FuncLayoutItem>; 
    FuncLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
};
   
class MsgLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<MsgLayoutItem>; 
    MsgLayoutItem(const std::string& str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
}; 

class StringLayoutItem : public LogLayout::LogLayoutItem
{
public:
    using ptr = std::shared_ptr<StringLayoutItem>; 
    StringLayoutItem(const std::string& str)
        : m_str(str) {}
    void format(std::ostream& os, const LogEvent::ptr ptrEvent);
private:
    std::string m_str;
};
   
} // namespace log
